﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SGLisp;

namespace SGLib.AITree
{
    class AICaseNode : AINode
    {
        ASTNode mCaseValueNode;
        List<ASTNode> mKeyNodes;
        List<AINode> mValueNodes;

        AINode mCurRuningNode;

        public AICaseNode(AITree tree)
        {
            mTree = tree;
        }
        public override void Load(ListNode astNode)
        {
            this.mNodeState = AINodeState.Wait;

            this.mKeyNodes = new List<ASTNode>();
            this.mValueNodes = new List<AINode>();
            this.mCaseValueNode = astNode.nodes.First.Next.Value;
            int Indexi = 1;

            foreach (ASTNode elemNode in astNode.nodes)
            {
                if (Indexi <= 2) continue;
                if ((Indexi % 2) == 1)
                {
                    this.mKeyNodes.Add(elemNode);
                }
                else
                {
                    this.mValueNodes.Add(this.mTree.ParseNode(elemNode));
                }
                Indexi++;
            }
        }

        public override void OnEnter(Context context)
        {
            this.mNodeState = AINodeState.Run;
        }

        public override void OnExit()
        {
            this.mNodeState = AINodeState.Finish;
        }

        public override void Update(Context context, float dt)
        {
            AINode caseValue = getCaseAINode(context);
            if (caseValue == null)
            {
                if (this.mCurRuningNode != null)
                {
                    this.mCurRuningNode.OnExit();
                    this.mCurRuningNode = null;
                }
                return;
            }
            if (mCurRuningNode == null)
            {
                this.mCurRuningNode = caseValue;
                this.mCurRuningNode.OnEnter(context);
            }
            else if (caseValue != this.mCurRuningNode)
            {
                this.mCurRuningNode.OnExit();
                this.mCurRuningNode = caseValue;
                this.mCurRuningNode.OnEnter(context);
            }
            this.mCurRuningNode.Update(context,dt);
            if (mCurRuningNode != null && this.mCurRuningNode.NodeState == AINodeState.Finish)
            {
                this.mCurRuningNode = null;
            }
        }

        AINode getCaseAINode(Context context)
        {
            ASTNode caseValueNode = RT.Evaluate(this.mCaseValueNode, context);
            object caseValue = RT.EvalNode(caseValueNode, context);
            for (int i = 0; i < this.mKeyNodes.Count; i ++)
            {
                ASTNode lispNode = this.mKeyNodes[i];
                ASTNode curValueNode = RT.Evaluate(lispNode, context);
                object  curValue = RT.EvalNode(curValueNode, context);
                if (caseValue == curValue)
                {
                    return this.mValueNodes[i];
                }
            }
            return null;
        }

    }
}
